﻿using AutoMapper;
using HamcoWcs.Contract;
using HamcoWcs.Contract.ContractCommon;
using HamcoWcs.DAL;
using HamcoWcs.Entitys.Logs;
using HamcoWcs.Entitys.Logss;
using HamcoWcs.Entitys.MesMsgQueues;
using HamcoWcs.Models.Common;
using HamcoWcs.Models.Common.Enums;
using HamcoWcs.Models.Exceptions;
using HamcoWcs.Models.Logs;
using HamcoWcs.Models.OperationLogs;
using NPOI.SS.Formula.Functions;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using Qin.Common;
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;

namespace HamcoWcs.Service.Common
{
    [AutoInject(typeof(ILoggerService), InjectType.Scope)]
    public class LoggerService : ScopeServiceBase, ILoggerService
    {
        private readonly IBaseConfigService _dic;
        private int _expiredDays = 180;
        private int _fileExpiredDays = 180;
        private int _expiredPlaybackDays = 180;
        public LoggerService(IBaseConfigService dic, IMapper mapper, WcsDbContext wcsDbContext)
            : base(wcsDbContext, mapper)
        {
            _dic = dic;
            var a1 = _dic.TryGetConfigValue("LOGDELETEEXPIRED", out string texpiredDays);
            if (a1)
            {
                var b1 = int.TryParse(texpiredDays, out int expiredDays);
                _expiredDays = b1 ? expiredDays  : _expiredDays;
            }

            var a2 = _dic.TryGetConfigValue("PLAYBACKDELETEEXPIRED", out string texpiredPlaybackDays);
            if (a2)
            {
                var b2 = int.TryParse(texpiredPlaybackDays, out int expiredPlaybackDays);
                _expiredPlaybackDays = b2 ? expiredPlaybackDays : _expiredPlaybackDays;
            }

            var a3 = _dic.TryGetConfigValue("FILELOGDELETEEXPIRED", out string fileExpiredDays);
            if (a3)
            {
                var b3 = int.TryParse(fileExpiredDays, out int expiredFileDays);
                _fileExpiredDays = b3 ? expiredFileDays : _fileExpiredDays;
            }
        }


        public void DeleteLog()
        {
            try
            {
                AddWcsRunLog("DoDeleteLog", "DeleteLog");
                DeletePayBackData();
                DeleteCommunicateLog();
            }
            catch(Exception e)
            {
                AddSystemErrorLog($"do delete file log error. ex = {e.Message}");
            }
            try
            {
                DeleteWcsRunLog();
                DeleteSystemErrorLog();
                DeleteOperationLog();
                DeleteLoginLog();
                DeleteDeviceErrorLog();
                DeleteMesMsgBak();
                DeleteFileLog();
                DeleteHBLog();
            }
            catch (Exception e)
            {
                AddSystemErrorLog($"do delete sql log error. ex = {e.Message}");
            }
           
        }

        #region DeviceErrorLog

        //public void AddDeviceErrorLog(string plcName, string deviceName, string errorCode, string errorDetail)
        //{
        //    var deviceErrorLogDto = new DeviceErrorLogDto(plcName, deviceName, errorCode, errorDetail);
        //    deviceErrorLogDto.SetTime = DateTime.Now;
        //    var addlog = _mapper.Map<DeviceErrorLog>(deviceErrorLogDto);

        //    var addlog = new DeviceErrorLog()
        //    {
        //        PlcName = plcName,
        //        DeviceName = deviceName,
        //        ErrorCode = errorCode,
        //        ErrorDetail = errorDetail,

        //    };
        //    _wcsDbContext.DeviceErrorLogs.Add(addlog);
        //    _wcsDbContext.SaveChanges();
        //}


        public void DeleteDeviceErrorLog()
        {
            try
            {
                var thresholdDate = DateTime.Now.AddDays(0 - _expiredDays);

                var expiredLogs = _wcsDbContext.DeviceErrorLogs
                               .AsQueryable()
                               .Where(d => d.CreatedTime < thresholdDate)
                               .ToList();

                if (expiredLogs?.Count > 0)
                {
                    var wb = new XSSFWorkbook();

                    ISheet st = ExcelHelper.SetSheet(wb, expiredLogs);
                    var dir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "logs", "deviceerror_logs");
                    if (!Directory.Exists(dir))
                    {
                        Directory.CreateDirectory(dir);
                    }
                    var path = Path.Combine(dir, $"{DateTime.Now:yyyyMMdd}.xlsx");
                    using (FileStream fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite))
                    {
                        wb.Write(fs);
                    }

                    _wcsDbContext.RemoveRange(expiredLogs);
                    _wcsDbContext.SaveChanges();
                    Console.WriteLine($"[DeviceErrorLog]删除了{expiredLogs.Count}条日志 ");
                }
            }
            catch (Exception exception)
            {
                Console.WriteLine(exception.ToString());
            }
            
        }

        #endregion

        #region DeviceMsgLog(Async)
        public void AddDeviceMsgLog(string plcName, string deviceName, string taskId, string unitId, string msgValue, string direction)
        {
            var deviceMsgLogDto = new DeviceMsgLogDto()
            {
                PlcName = plcName,
                DeviceName = deviceName,
                TaskId = taskId,
                UnitId = unitId,
                MsgValue = msgValue,
                Direction = direction
            };

            var addlog = _mapper.Map<DeviceMsgLog>(deviceMsgLogDto);
            _wcsDbContext.DeviceMsgLogs.Add(addlog);
            _wcsDbContext.SaveChanges();
        }
        //public void BackupDeviceMsgLog()
        //{
        //    var logs = _wcsDbContext.DeviceMsgLogs.AsQueryable().ToList();
        //    if (logs?.Count > 0)
        //    {
        //        var logBaks = _mapper.Map<List<DeviceMsgLogBak>>(logs);
        //        _wcsDbContext.AddRange(logBaks);
        //        _wcsDbContext.RemoveRange(logs);
        //        _wcsDbContext.SaveChanges();
        //    }
        //}
        public void DeleteDeviceMsgLog()
        {
            var expiredLogs = _wcsDbContext.DeviceErrorLogs
                           .AsQueryable()
                           .Where(d => d.CreatedTime < DateTime.Now.AddDays(0 - _expiredDays))
                           .ToList();
            if (expiredLogs?.Count > 0)
            {
                _wcsDbContext.DeviceErrorLogs.RemoveRange(expiredLogs);
                _wcsDbContext.SaveChanges();
            }

        }

        #endregion

        #region LoginLog
        public void InsertLoginLog(string userName, string loginIp)
        {
            if (loginIp == null) loginIp = "";
            var loginLogDto = new LoginLogDto(userName, loginIp);
            var loginLog = _mapper.Map<LoginLog>(loginLogDto);

            try
            {
                _wcsDbContext.LoginLogs.Add(loginLog);
                _wcsDbContext.SaveChanges();
            }
            catch (Exception ex)
            {
                AddSystemErrorLog("LoggerService:" + ex.Message);
            }
        }

        #endregion

        #region OperationLog
        public void AddOperationLog(string userName, string controller, string methodName, string unitId, string deviceName, string remark)
        {
            var operationLogDto = new OperationLogDto(userName, controller, methodName, unitId, deviceName, remark);
            var addlog = _mapper.Map<OperationLog>(operationLogDto);
            _wcsDbContext.OperationLogs.Add(addlog);
            _wcsDbContext.SaveChanges();
        }

        #endregion

        #region SystemErrorLog
        public void AddSystemErrorLog(string log)
        {
            var systemErrorLogDto = new SystemErrorLogDto(log);
            var addlog = _mapper.Map<SystemErrorLog>(systemErrorLogDto);
            _wcsDbContext.SystemErrorLogs.Add(addlog);
            _wcsDbContext.SaveChanges();
        }

        #endregion

        #region WcsRunLog（Async）
        public void AddWcsRunLog(string unitId, string msgValue)
        {
            var wcsRunLogDto = new WcsRunLogDto(unitId, msgValue);
            var addlog = _mapper.Map<WcsRunLog>(wcsRunLogDto);
            _wcsDbContext.WcsRunLogs.Add(addlog);
            _wcsDbContext.SaveChanges();
        }

        public void AddWcsRunLog(WcsRunException exception)
        {
            AddWcsRunLog(exception.UnitId, exception.Message);
        }

        //public void BackupWcsRunLog()
        //{
        //    var logs = _wcsDbContext.WcsRunLogs.AsQueryable().ToList();
        //    if (logs?.Count > 0)
        //    {
        //        var logBaks = _mapper.Map<List<WcsRunLogBak>>(logs);
        //        _wcsDbContext.AddRange(logBaks);
        //        _wcsDbContext.RemoveRange(logs);
        //        _wcsDbContext.SaveChanges();
        //    }
        //}
        public void DeleteWcsRunLog()
        {
            try
            {
                var thresholdDate = DateTime.Now.AddDays(0 - _expiredDays);

                var expiredLogs = _wcsDbContext.WcsRunLogs
                               .AsQueryable()
                               .Where(d => d.CreatedTime < thresholdDate)
                               .ToList();

                if (expiredLogs?.Count > 0)
                {
                    //将超过指定日期的日志保存为Excel
                    var wb = new XSSFWorkbook();

                    ISheet st = ExcelHelper.SetSheet(wb, expiredLogs);
                    var dir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "logs", "wcsrun_logs");
                    if (!Directory.Exists(dir))
                    {
                        Directory.CreateDirectory(dir);
                    }
                    var path = Path.Combine(dir, $"{DateTime.Now:yyyyMMdd}.xlsx");
                    using (FileStream fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite))
                    {
                        wb.Write(fs);
                    }
                    //删除超过指定日期的日志
                    _wcsDbContext.RemoveRange(expiredLogs);
                    _wcsDbContext.SaveChanges();
                   AddWcsRunLog("DeleteWcsRunLog", $"[WcsRunLog]删除了{expiredLogs.Count}条日志 ");
                }
            }
            catch (Exception exception) 
            {
               AddSystemErrorLog(exception.Message);
            }
           
        }

        #endregion

        public void AddCommunicationLog(CommunicationLog log)
        {
            _wcsDbContext.Set<CommunicationLog>().Add(log);
            _wcsDbContext.SaveChanges();
        }

        public void AddCommunicationLogs(List<CommunicationLog> logs)
        {
            _wcsDbContext.Set<CommunicationLog>().AddRange(logs);
            _wcsDbContext.SaveChanges();
        }

        public void DeleteSystemErrorLog()
        {
            try
            {
                var thresholdDate = DateTime.Now.AddDays(0 - _expiredDays);

                var expiredLogs = _wcsDbContext.SystemErrorLogs
                               .AsQueryable()
                               .Where(d => d.CreatedTime < thresholdDate)
                               .ToList();

                if (expiredLogs?.Count > 0)
                {
                    var wb = new XSSFWorkbook();

                    ISheet st = ExcelHelper.SetSheet(wb, expiredLogs);
                    var dir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "logs", "systemerror_logs");
                    if (!Directory.Exists(dir))
                    {
                        Directory.CreateDirectory(dir);
                    }
                    var path = Path.Combine(dir, $"{DateTime.Now:yyyyMMdd}.xlsx");
                    using (FileStream fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite))
                    {
                        wb.Write(fs);
                    }

                    _wcsDbContext.RemoveRange(expiredLogs);
                    _wcsDbContext.SaveChanges();
                   AddWcsRunLog("DeleteSystemErrorLog", $"[SystemErrorLog]删除了{expiredLogs.Count}条日志 ");
                }
                }
            catch (Exception exception) 
            {
               AddSystemErrorLog(exception.Message);
            }
        }

        public void DeleteOperationLog()
        {
            try
            {
                var thresholdDate = DateTime.Now.AddDays(0 - _expiredDays);

                var expiredLogs = _wcsDbContext.OperationLogs
                               .AsQueryable()
                               .Where(d => d.CreatedTime < thresholdDate)
                               .ToList();

                if (expiredLogs?.Count > 0)
                {
                    //var name = thresholdDate.ToString("yyyyMMdd") + "_OperationLog.xlsx";
                    //// 指定Excel文件的保存路径和名称  
                    //string excelFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, name);

                    //// 保存过期日志到Excel文件  
                    //SaveExpiredLogsToExcel(expiredLogs, excelFilePath);

                    var wb = new XSSFWorkbook();

                    ISheet st = ExcelHelper.SetSheet(wb, expiredLogs);
                    var dir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "logs", "operation_logs");
                    if (!Directory.Exists(dir))
                    {
                        Directory.CreateDirectory(dir);
                    }
                    var path = Path.Combine(dir, $"{DateTime.Now:yyyyMMdd}.xlsx");
                    using (FileStream fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite))
                    {
                        wb.Write(fs);
                    }

                    // 从数据库中删除过期日志  
                    _wcsDbContext.RemoveRange(expiredLogs);
                    _wcsDbContext.SaveChanges();
                   AddWcsRunLog("DeleteOperationLog", $"[OperationLog]删除了{expiredLogs.Count}条日志 ");
                }
            }
            catch (Exception exception)
            {
               AddSystemErrorLog(exception.Message);
            }
        }

        public void DeleteLoginLog()
        {
            try
            {
                var thresholdDate = DateTime.Now.AddDays(0 - _expiredDays);

                var expiredLogs = _wcsDbContext.LoginLogs
                               .AsQueryable()
                               .Where(d => d.CreatedTime < thresholdDate)
                               .ToList();

                if (expiredLogs?.Count > 0)
                {
                    var wb = new XSSFWorkbook();

                    ISheet st = ExcelHelper.SetSheet(wb, expiredLogs);
                    var dir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "logs", "login_logs");
                    if (!Directory.Exists(dir))
                    {
                        Directory.CreateDirectory(dir);
                    }
                    var path = Path.Combine(dir, $"{DateTime.Now:yyyyMMdd}.xlsx");
                    using (FileStream fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite))
                    {
                        wb.Write(fs);
                    }

                    _wcsDbContext.RemoveRange(expiredLogs);
                    _wcsDbContext.SaveChanges();
                   AddWcsRunLog("DeleteLoginLog", $"[LoginLog]删除了{expiredLogs.Count}条日志 ");
                }
            }
            catch (Exception exception)
            {
               AddSystemErrorLog(exception.Message);
            }
        }

        public void DeleteMesMsgBak()
        {
            try
            {
                var thresholdDate = DateTime.Now.AddDays(-3);

                var expiredLogs = _wcsDbContext.Set<MesMsgQueueBak>()
                               .AsQueryable()
                               .Where(d => d.CreatedTime < thresholdDate)
                               .ToList();

                if (expiredLogs?.Count > 0)
                {
                    var wb = new XSSFWorkbook();

                    ISheet st = ExcelHelper.SetSheet(wb, expiredLogs);
                    var dir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "logs", "mesmsgqueuebak_logs");
                    if (!Directory.Exists(dir))
                    {
                        Directory.CreateDirectory(dir);
                    }
                    var path = Path.Combine(dir, $"{DateTime.Now:yyyyMMdd}.xlsx");
                    using (FileStream fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite))
                    {
                        wb.Write(fs);
                    }

                    _wcsDbContext.RemoveRange(expiredLogs);
                    _wcsDbContext.SaveChanges();
                   AddWcsRunLog("DeleteMesMsgBak", $"[MesMsgQueueBak]删除了{expiredLogs.Count}条日志 ");
                }
            }
            catch (Exception exception)
            {
               AddSystemErrorLog(exception.Message);
            }
        }

        public void DeletePayBackData()
        {
            try
            {
                var expiredDate = DateTime.Now.AddDays(0 - _expiredPlaybackDays);
                if (!Directory.Exists(GlobalValue.PlaybackLogFolder)) return;

                var files = Directory.GetFiles(GlobalValue.PlaybackLogFolder);
                foreach (var file in files)
                {
                    var fileName = Path.GetFileNameWithoutExtension(file);
                    if (fileName.Length < 8) continue;

                    var dateStr = fileName.Substring(0, 8).Insert(6, "-").Insert(4, "-");

                    DateTime fileDate;
                    try
                    {
                        fileDate = DateTime.Parse(dateStr);
                    }
                    catch (Exception)
                    {
                        continue;
                    }

                    try
                    {
                        if (fileDate < expiredDate)
                        {
                            File.Delete(file);
                        }
                    }
                    catch (Exception)
                    {
                        continue;
                    }
                }
            }
            catch (Exception exception)
            {
               AddSystemErrorLog(exception.Message);
            }
        }

        public void DeleteCommunicateLog()
        {
            try
            {
                var expiredDate = DateTime.Now.AddDays(0 - _expiredDays);
                
                if (!Directory.Exists(GlobalValue.CommunicateLogFolder)) return;

                var files = Directory.GetFiles(GlobalValue.CommunicateLogFolder);
                foreach (var file in files)
                {
                    var fileName = Path.GetFileNameWithoutExtension(file);
                    if (fileName.Length < 8) continue;

                    var dateStr = fileName.Substring(0, 8).Insert(6, "-").Insert(4, "-");

                    DateTime fileDate;
                    try
                    {
                        fileDate = DateTime.Parse(dateStr);
                    }
                    catch (Exception)
                    {
                        continue;
                    }

                    try
                    {
                        if (fileDate < expiredDate)
                        {
                            File.Delete(file);
                            Console.WriteLine($"[Delete]{file}");
                        }
                    }
                    catch (Exception)
                    {
                        continue;
                    }
                }
            }
            catch (Exception exception)
            {
               AddSystemErrorLog(exception.Message);
            }
        }

        public void DeleteFileLog()
        {
            try
            {
                var expiredDate = DateTime.Now.AddDays(0 - _fileExpiredDays);
                var mesmsgqueuebakLogFolder = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "logs", "mesmsgqueuebak_logs");
                var loginLogFolder = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "logs", "login_logs");
                var operationLogFolder = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "logs", "operation_logs");
                var systemerrorLogFolder = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "logs", "systemerror_logs");
                var wcsrunLogFolder = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "logs", "wcsrun_logs");
                var deviceerrorLogFolder = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "logs", "deviceerror_logs");
                List<string> folders = new List<string>()
            {
                mesmsgqueuebakLogFolder,
                loginLogFolder,
                operationLogFolder,
                systemerrorLogFolder,
                wcsrunLogFolder,
                deviceerrorLogFolder
            };
                foreach (var folder in folders)
                {
                    if (!Directory.Exists(folder)) continue;

                    var files = Directory.GetFiles(folder);
                    foreach (var file in files)
                    {
                        var fileName = Path.GetFileNameWithoutExtension(file);
                        if (fileName.Length < 8) continue;

                        var dateStr = fileName.Substring(0, 8).Insert(6, "-").Insert(4, "-");

                        DateTime fileDate;
                        try
                        {
                            fileDate = DateTime.Parse(dateStr);
                        }
                        catch (Exception)
                        {
                            continue;
                        }

                        try
                        {
                            if (fileDate < expiredDate)
                            {
                                File.Delete(file);
                                Console.WriteLine($"[Delete]{file}");
                            }
                        }
                        catch (Exception)
                        {
                            continue;
                        }
                    }
                }
            }
            catch (Exception exception)
            {
               AddSystemErrorLog(exception.Message);
            }  
        }

        public void DeleteHBLog()
        {
            try
            {
                var expiredDate = DateTime.Now.AddDays(-2);

                var expiredLogs = _wcsDbContext.Set<CommunicationLogBak>()
                       .AsQueryable()
                       .Where(d => d.CreatedTime < expiredDate)
                       .ToList();

                if (expiredLogs?.Count > 0)
                {
                    _wcsDbContext.RemoveRange(expiredLogs);
                    _wcsDbContext.SaveChanges();
                    Console.WriteLine($"[HB Log]删除了{expiredLogs.Count}条日志 ");
                }
            }
            catch (Exception exception)
            {
               AddSystemErrorLog(exception.Message);
            }
        }

        //public void SaveExpiredLogsToExcel(List<OperationLog> logs, string filePath)
        //{
        //    using (ExcelPackage package = new ExcelPackage())
        //    {
        //        var worksheet = package.Workbook.Worksheets.Add("Expired Logs");

        //        // 写入表头  
        //        worksheet.Cells[1, 1].Value = "ID";
        //        worksheet.Cells[1, 2].Value = "UserName";
        //        worksheet.Cells[1, 3].Value = "UnitId";
        //        worksheet.Cells[1, 4].Value = "DviceName";
        //        worksheet.Cells[1, 5].Value = "Remark";
        //        worksheet.Cells[1, 6].Value = "Created Time";
        //        worksheet.Cells[1, 7].Value = "LastUpdateTime";
        //        worksheet.Cells[1, 8].Value = "Controller";
        //        worksheet.Cells[1, 9].Value = "MethodName;";


        //        // ... 添加其他你希望保存的列标题  

        //        // 写入日志数据  
        //        int row = 2;
        //        foreach (var log in logs)
        //        {
        //            worksheet.Cells[row, 1].Value = log.Id;
        //            worksheet.Cells[row, 2].Value = log.UserName;
        //            worksheet.Cells[row, 3].Value = log.UnitId;
        //            worksheet.Cells[row, 4].Value = log.DeviceName;
        //            worksheet.Cells[row, 5].Value = log.Remark;
        //            worksheet.Cells[row, 6].Value = log.CreatedTime.ToString();
        //            worksheet.Cells[row, 7].Value = log.LastUpdateTime.ToString();
        //            worksheet.Cells[row, 8].Value = log.Controller;
        //            worksheet.Cells[row, 9].Value = log.MethodName;
        //        // ... 填充其他列的数据  
        //        row++;
        //        }

        //        // 保存Excel文件  
        //        FileInfo excelFile = new FileInfo(filePath);
        //        package.SaveAs(excelFile);
        //    }
        //}
    }
}
